fn main() {
    println!("闭包, 涉及到借用 还是没明白.");
    // 1. 用 || 替代 ()
    // 2. 单个表达式 {} 可选
    // 3. 能捕捉外部变量

    // 用 fn 实现
    fn func(i: i32) -> i32 {
        i + 1
    }
    println!("fn +1: {}", func(1));

    // 用闭包实现
    let add = |i: i32| i + 1;
    println!("closure +1: {}", add(1));

    // 捕捉变量
    // 1. &T
    // 2. &mut T
    // 3. T

    let color = String::from("green");
    // 这个闭包打印 `color`。它会立即借用（通过引用，`&`）`color` 并将该借用和
    // 闭包本身存储到 `print` 变量中。`color` 会一直保持被借用状态直到
    // `print` 离开作用域。
    //
    // `println!` 只需传引用就能使用，而这个闭包捕获的也是变量的引用，因此无需
    // 进一步处理就可以使用 `println!`。
    let print = || println!("{}", color);
    // 使用闭包
    print();

    // `color` 可再次被不可变借用，因为闭包只持有一个指向 `color` 的不可变引用
    let _reborrow = &color; // 再次引用
    print();

    // 重新借用,或移动是允许的
    let _color_moved = color;

    let mut count = 1;
    let mut inc = || {
        count += 1;
        println!("加1之后: {}", count);
    };
    // count ++
    inc();

    // 二次借用示例
    let mut _borrow = count; // use of borrowed `count`
                             // inc(); 此行与上一行只能同时存在一个

    _borrow += 1;
    println!("{}", _borrow);

    // 在竖线 | 之前使用 move 会强制闭包取得被捕获变量的所有权：
    let hayhacks = vec![1, 2, 3];
    let contains = move |needle| hayhacks.contains(needle);

    // 调用闭包会 move 变量所有权
    println!("{}", contains(&1));
    println!("{}", contains(&2));

    // 已经 move 到 containes 闭包里了, 此后不能再用.
    // borrow of moved value: `hayhacks`
    // println!("{}", hayhacks.len());
}
